<template>
  <div class="w-full h-full cabinet-formula_detail">
    <vxe-card
      title=""
      class="w-full h-[calc(100%_-_32px)]"
      :padding="false"
      :border="false"
    >
      <vxe-tabs v-model="activeName" @change="tabChange">
        <vxe-tab-pane :title="t('formula_detail.basic_info')" name="first" />
        <vxe-tab-pane
          :title="t('formula_detail.material_select')"
          name="second"
        />
        <vxe-tab-pane
          :title="t('formula_detail.material_ratio')"
          name="third"
        />
      </vxe-tabs>

      <div class="p-[20px]">
        <el-scrollbar
          v-show="activeName === 'first'"
          height="calc(100vh - 220px)"
        >
          <BaseInfo
            ref="baseInfoRef"
            :baseData="baseData"
            :specCheckList="specCheckList"
            @pageBefore="pageBefore"
            @specChange="specChange"
          />
        </el-scrollbar>
        <MaterialSet
          v-show="activeName === 'second'"
          ref="materialSetRef"
          :matIds="matIds"
          :materialList="materialList"
          @pageBefore="pageBefore"
          @matIdsChange="matIdsChange"
        />
        <MatMatch
          v-show="activeName === 'third'"
          ref="matMatchRef"
          :materialRatioData="materialRatioData"
        />
      </div>
      <div
        class="flex justify-end p-[10px] border-t border-[--autata-border-color]"
      >
        <el-button type="primary" plain @click="cancel">{{
          t("formula_detail.back")
        }}</el-button>
        <el-button type="primary" @click="throttle(saveFormula, 1000)()">{{
          t("formula_detail.save")
        }}</el-button>
      </div>
    </vxe-card>
  </div>
</template>

<script setup lang="ts">
import { getCurrentInstance, onBeforeMount, onMounted, ref } from "vue";
import BaseInfo from "./components/BaseInfo.vue";
import MaterialSet from "./components/MaterialSet.vue";
import { useCabinetStore } from "@/store/modules/cabinet";
import { useRoute, useRouter } from "vue-router";
import { isArray, isString } from "@pureadmin/utils";
import MatMatch from "@/views/cabinet/formula/formulaDetail/components/MatMatch.vue";
import {
  formulaAdd,
  formulaGetDetail,
  formulaUpd,
  thirdRelationGetListAll
} from "@/api/cabinet/formulaDetail";
import { ElMessage } from "element-plus";
import { throttle, omit } from "lodash-unified";
import { useI18n } from "vue-i18n";

const { t } = useI18n();
defineOptions({
  name: "CabinetFormulaDetail"
});

const { proxy } = getCurrentInstance();
const cabinetStore = useCabinetStore();
const route = useRoute();
const router = useRouter();

const activeName = ref("first");

const baseData = ref(null);
const baseInfoRef = ref();

const matIds = ref([]);
const materialList = ref([]);
const materialSetRef = ref();

const matMatchRef = ref();
const materialRatioData = ref([]);

const specCheckList = ref([]);

let globalMaterialRatio = cabinetStore.formulaDetail ?? [];
let specsOriginalData = [];

// region -------------------------------- 通用方法 ----------------------------------

//笛卡尔积生成
function cartesianProduct(arr) {
  if (arr.length < 2) return arr[0] || [];
  return [].reduce.call(arr, function (col, set) {
    let res = [];
    col.forEach(c => {
      set.forEach(s => {
        let t = [].concat(Array.isArray(c) ? c : [c]);
        t.push(s);
        res.push(t);
      });
    });
    return res;
  });
}

//配置物料配比数据
function configMaterialRatioData() {
  let showArray = [];
  let tableData = materialSetRef.value.getMatList();
  if (tableData.length > 0) {
    //替换成需要的字段数据
    let newTableArray = [];
    for (let i = 0; i < tableData.length; i++) {
      let newTableObject = {};
      newTableObject["material_id"] = tableData[i].material_id;
      newTableObject["material_name"] = tableData[i].name;
      if (
        tableData[i].standard_amount == undefined ||
        tableData[i].standard_amount == null ||
        tableData[i].standard_amount == ""
      ) {
        newTableObject["amount"] = "";
      } else {
        newTableObject["amount"] = tableData[i].standard_amount;
      }
      newTableObject["amount_unit"] = tableData[i].amount_unit;
      newTableArray.push(newTableObject);
    }
    tableData = newTableArray;
    let array = [];
    let array_id = [];
    for (let i = 0; i < specsOriginalData.length; i++) {
      let check_attrs = [];
      let check_attr = specsOriginalData[i].check_attr;
      if (check_attr != undefined && check_attr != "") {
        check_attrs = check_attr.split(",");
      }
      check_attrs = check_attrs.filter(function (s) {
        return s && s.trim();
      });
      if (check_attrs.length > 0) {
        array.push(check_attrs);
        let check_attrs_id = [];
        for (let l = 0; l < check_attrs.length; l++) {
          check_attrs_id.push(specsOriginalData[i].id);
        }
        array_id.push(check_attrs_id);
      }
    }
    if (array.length > 0) {
      let newArray = cartesianProduct(array);
      let newArrayId = cartesianProduct(array_id);
      for (let s = 0; s < newArray.length; s++) {
        let showObject = {};
        let showDetailArray = [];
        if (Array.isArray(newArray[s])) {
          for (let p = 0; p < newArray[s].length; p++) {
            let showDetailObject = {};
            showDetailObject["specification_id"] = newArrayId[s][p];
            showDetailObject["attr"] = newArray[s][p];
            showDetailArray.push(showDetailObject);
          }
        } else {
          let showDetailObject = {};
          showDetailObject["specification_id"] = newArrayId[s];
          showDetailObject["attr"] = newArray[s];
          showDetailArray.push(showDetailObject);
        }
        showObject["materialSpecs"] = showDetailArray;
        showObject["materialAmount"] = tableData;
        showArray.push(showObject);
      }
    }
  }
  let oldMaterialRatio = globalMaterialRatio; //物料配比数据(全局)
  for (let i = 0; i < showArray.length; i++) {
    let materialAmount = JSON.parse(
      JSON.stringify(showArray[i].materialAmount)
    );
    let materialSpecs = JSON.parse(JSON.stringify(showArray[i].materialSpecs));
    let materialSpecsText = "";
    for (let p = 0; p < materialSpecs.length; p++) {
      materialSpecsText += materialSpecs[p].attr;
    }
    let oldMaterialAmount = [];
    //判断规格是否一样
    myFor: for (let l = 0; l < oldMaterialRatio.length; l++) {
      let oldMaterialSpecs = oldMaterialRatio[l].materialSpecs;
      let oldMaterialSpecsText = "";
      for (let k = 0; k < oldMaterialSpecs.length; k++) {
        oldMaterialSpecsText += oldMaterialSpecs[k].attr;
      }
      if (materialSpecsText == oldMaterialSpecsText) {
        oldMaterialAmount = oldMaterialRatio[l].materialAmount;
        break myFor;
      }
    }
    //更新物料用量数据
    for (let l = 0; l < materialAmount.length; l++) {
      for (let k = 0; k < oldMaterialAmount.length; k++) {
        if (materialAmount[l].material_id == oldMaterialAmount[k].material_id) {
          materialAmount[l].amount = oldMaterialAmount[k].amount;
          showArray[i]["materialAmount"] = materialAmount;
        }
      }
    }
    showArray[i]["edit_status"] = 3; //状态 1 绿色 2 黄色 3 红色
  }
  //更新物料配比编辑状态
  for (let i = 0; i < showArray.length; i++) {
    let status = false; //物料用量是否有空
    let materialAmount = showArray[i].materialAmount;
    for (let l = 0; l < materialAmount.length; l++) {
      if (
        materialAmount[l].amount == undefined ||
        materialAmount[l].amount == ""
      ) {
        status = true;
      }
    }
    if (status) {
      showArray[i]["edit_status"] = 3; //状态 1 绿色 2 黄色 3 红色
    } else {
      showArray[i]["edit_status"] = 1; //状态 1 绿色 2 黄色 3 红色
    }
  }
  console.log("showArray", showArray);
  // showMaterialRatioData(showArray);
  materialRatioData.value = showArray;
}

function getFormulaDetail() {
  if (isString(route.query?.row)) {
    const row = JSON.parse(route.query?.row);
    formulaGetDetail(row).then(res => {
      const data = res.data;
      const tag_list: { id: number; name: string }[] = JSON.parse(
        data.tag_list
      );
      const baseInfo = {
        formula_subid: data.formula_subid,
        formula_id: data.formula_id,

        icon: data.icon,
        name: data.name,
        note: data.note,
        tag_list,
        tag: tag_list.map(v => v.id),
        is_effective: data.is_effective,
        third_value: data.third_value,
        publish_status: data.publish_status,

        version: data.version
      };
      baseData.value = baseInfo;

      matIds.value = data.material_list?.map(v => v.material_id) ?? [];
      materialList.value = data.material_list;

      baseInfoRef.value.setSpecList(data.specification_list);

      materialRatioData.value = data.formula_detail;
    });
  }
}

// endregion

const tabChange = ({ value }) => {
  cabinetStore.changeActiveName(value);
};

const specListHandle = specList => {
  return specList.map(v => {
    return {
      ...v,
      check_attr: v.attr
        .filter(h => h.checked)
        .map(h => h.name)
        .join(","),
      attr: v.attr.map(h => h.name).join(",")
    };
  });
};

const specChange = specList => {
  cabinetStore.changeSpecList(specList);
  if (isArray(specList)) {
    specsOriginalData = specListHandle(specList);
    configMaterialRatioData();
  }
};

const matIdsChange = () => {
  specsOriginalData = specListHandle(baseInfoRef.value.getSpecList());
  configMaterialRatioData();
};

const pageBefore = () => {
  const baseInfo = baseInfoRef.value.getBaseInfo();
  cabinetStore.changeBaseInfo(baseInfo);
  console.log(materialSetRef.value);

  const matIds = materialSetRef.value.getMatIds();
  cabinetStore.changeMaterialIds(matIds);
  const matList = materialSetRef.value.getMatList();
  cabinetStore.changeMaterialList(matList);

  const formulaDetail = matMatchRef.value.getAmountData();
  cabinetStore.changeFormulaDetail(formulaDetail);
};

const cancel = () => {
  cabinetStore.clearState();

  router.push({
    name: "CabinetFormulaList",
    query: {
      version: route.query.version
    }
  });
};

function effectiveHandle(
  third_value: string,
  isEffective: string
): Promise<{
  flag: boolean;
  type?: number;
  firstId?: string;
}> {
  return new Promise((resolve, reject) => {
    if (isEffective) {
      resolve({ flag: true });
      return;
    }
    const param = {
      start_page: 0,
      size: 0,
      thirdRelation: {
        third_value
      }
    };
    thirdRelationGetListAll(param).then(res => {
      const d = res;
      if (d.code === 200) {
        if (d.data.length) {
          const filterList = d.data.filter(item => item.is_effective == "1");
          const firstId = d.data[0].autata_value;

          if (!filterList.length && !isEffective) {
            proxy.$auMessageBox
              .confirm(t("formula_detail.priority_confirm"), t("notice.title"))
              .then(() => {
                resolve({ flag: false, type: 1, firstId });
              })
              .catch(() => {
                resolve({ flag: true });
              });
          } else {
            resolve({ flag: true });
          }
        } else {
          resolve({ flag: false, type: 0 });
        }
      } else {
        resolve({ flag: false, type: 0 });
      }
    });
  });
}

function RegInt(value) {
  return /^[1-9]\d*$/.test(value);
}

const validate = () => {
  const baseInfoValid = baseInfoRef.value.validate();
  if (!baseInfoValid) {
    activeName.value = "first";
    return false;
  }
  const matList = materialSetRef.value.getMatList();
  if (!matList.length) {
    proxy.$auMessageBox.alert(
      t("formula_detail.add_material"),
      t("notice.title")
    );
    activeName.value = "second";
    return false;
  }
  for (var i = 0; i < matList.length; i++) {
    if (!RegInt(matList[i].index)) {
      const info = t("formula_detail.material_order_error");
      proxy.$auMessageBox.alert(info, t("notice.title"));
      return false;
    }
    matList[i].overdue_time = matList[i].overdue_time * 1000 * 60 * 60;
    matList[i].cold_time = matList[i].cold_time * 1000 * 60 * 60;
  }

  const matMatchValid = matMatchRef.value.validate();
  if (!matMatchValid) {
    activeName.value = "third";
    return false;
  }
  return { matList };
};

const saveFormula = async () => {
  const valid = validate();
  if (!valid) return;
  const formula_detail = matMatchRef.value.getAmountData();
  const version = JSON.parse(route.query?.version as string)?.id;
  const baseInfo = baseInfoRef.value.getBaseInfo();
  const param: { [key: string]: any } = {
    formula_subid: "",
    ...omit(baseInfo, ["tag"]),
    tag_list: JSON.stringify(baseInfo.tag_list),
    specification_list: JSON.stringify(specsOriginalData),
    material_list: JSON.stringify(valid.matList ?? []),
    formula_detail: JSON.stringify(formula_detail),
    version
  };
  console.log(param);
  let service = formulaAdd;
  if (param.formula_subid) {
    service = formulaUpd;
  }

  if (param.third_value) {
    const { flag, type: effectType } = await effectiveHandle(
      param.third_value,
      param.is_effective
    );
    if (flag) {
      param.is_effective = "1";
    } else if (!flag && effectType === 0) {
      param.is_effective = "1";
    }
  }
  service(param).then(res => {
    if (res.code === 200) {
      ElMessage({
        message: param.formula_subid
          ? t("formula_detail.edit_success")
          : t("formula_detail.add_success"),
        type: "success",
        grouping: true
      });
      if (!param.formula_subid) {
        baseData.value = {
          ...baseData.value,
          formula_subid: res.data.formula_subid
        };
      }
      if (activeName.value === "third") {
        cancel();
      }
    }
  });
};

onBeforeMount(() => {
  activeName.value = cabinetStore.activeName || "first";
  baseData.value = cabinetStore.baseInfo;
  if (!baseData.value?.formula_subid) {
    getFormulaDetail();
  }
  materialList.value = cabinetStore.materialList;
  if (route.query.matIds) {
    matIds.value = JSON.parse(route.query.matIds as string);
  } else {
    matIds.value = cabinetStore.materialIds;
  }
  specCheckList.value = cabinetStore.specList;
});
</script>

<style scoped lang="scss">
.cabinet-formula_detail {
  padding: 0 16px !important;

  :deep(.vxe-tabs-header--item-inner) {
    height: 50px;
    line-height: 50px;
  }
}
</style>
